//
/*   Macros and Utility functions  for Matrix * Vector operation program
*    Copyright (C) 2009 Goffredo Marocchi
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#ifndef IGGS_MATTEST_DEFINES_H
#define IGGS_MATTEST_DEFINES_H

//////////

#include "IGGS_PC_defines.h"
//#include "errlib.h"
//#include "msglib.h"

//////////

#define null (NULL) /**< \brief I like my Java style defined null pointer :).*/

#define PRINT_N(X) send_msg ("\n ---%d ---\n", X)

#define BLOCK_SIZE (2) /**< \brief The number of threads in a Thread Block (CUDA). */
#define AMP (2) /**< amplification factor, the way it is used it helps determine the number of Thread Blocks in a Grid */

#define STEPS (1) /**< \brief number of repetitions. */

#define PINNED (1) /**< \brief PINNED == 0 --> using PAGED memory.\n PINNED == 1 --> using fast PINNED memory. */

#define CUDA (0) /**< \brief CUDA == 0 --> CUBLAS execution path.\n CUDA == 1 --> CUDA execution path. */

#define TBLOCK (BLOCK_SIZE*BLOCK_SIZE)

#define ROWS (AMP*TBLOCK) /**< \brief Number of Rows in the source matrix and the source column vector.
											 \sa BLOCK_SIZE, AMP*/
#define COLS (AMP*TBLOCK) /**< \brief Number of Columns in the source matrix.
											 \sa BLOCK_SIZE, AMP*/
#define N_EL (ROWS) /**< \brief Number of elements in a column vector.
											 \sa BLOCK_SIZE, AMP*/

#define EQ(n1,n2) (n1 == n2)

#define N_MAT (ROWS * COLS) /**< \brief Number of elements (Rows * Columns) in the source matrix.
											 \sa ROWS, COLS*/
const u64 DATA_M = (N_MAT * sizeof(float)); /**< \brief Amount of bytes used to store the source matrix.
											 \sa N_MAT*/
const u64 DATA_V = (N_EL * sizeof(float)); /**< \brief Amount of bytes used to store the column vector (source and result).
											 \sa N_EL*/

#define PRINT_POINTER(x) (send_msg ("\nPointer is: %p", (x)))
#define PRINT_MAT_DIM(R,C) (send_msg ("Matrix is %dx%d", (R),(C)))
#define PRINT_CVEC_DIM(R) (send_msg ("Vector is %dx1", (R)))
#define PRINT_RVEC_DIM(C) (send_msg ("Vector is 1x%d", (C)))

#define PRINTLN send_msg ("");

#define P_MATR(mat, i, j, NCOLS) (*(mat))[indexR((i),(j),(NCOLS))]
#define MATR(mat, i, j, NCOLS) mat[indexR((i),(j),(NCOLS))]

#define P_MATC(mat, i, j, NROWS) (*(mat))[indexC((i),(j),(NROWS))] /**< \brief This macro dereferences the pointer to the matrix
																				and accesses it.
																		* \sa indexC(), NROWS */
#define MATC(mat, i, j, NROWS) mat[indexC((i),(j),(NROWS))]

#define IDX2F(i,j,ld) ((((j)-1)*(ld))+((i)-1)) //column major order addressing + 1st element has id#1
#define IDX2C(i,j,ld) (((j)*(ld))+(i)) //column major order addressing + 1st element has id#0

////////////////////////////////////////////////////////////////////////////////
// Helper MACRO to correctly index an 1D array as if it were a 2D one
////////////////////////////////////////////////////////////////////////////////
#define indexR(i, j, n_cols) ((j) + ((i) * (n_cols))) /**< \brief This macro provides row-major order addressing. */
#define indexC(i ,j, n_rows) (((j) * (n_rows)) + (i)) /**< \brief This macro provides column-major order addressing + 1st element has id#0 */



#define CHECK_BANK_CONFLICTS 0
#if CHECK_BANK_CONFLICTS
#define AS(i, j) CUT_BANK_CHECKER(((float*)&As[0][0]), (BLOCK_SIZE * i + j))
#define BS(i, j) CUT_BANK_CHECKER(((float*)&Bs[0][0]), (BLOCK_SIZE * i + j))
#else
#define AS(i, j) As[i][j]
#define BS(i, j) Bs[i][j]
#define BV(id) Bv[id]
#endif

#define CODE_INFO 1

#if CODE_INFO == 1
	#define PRINT_STEP() send_msg("Line: %i, File: %s", __LINE__, __FILE__)
#else
	#define PRINT_STEP()
#endif

#endif
